package models;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import play.db.jpa.Model;

@Entity
public class Dieta extends Model {    
	
	@Temporal(TemporalType.DATE)
	private Date fecha;
	
	@ManyToOne
	private Plan plan;
	
	@OneToMany(cascade=CascadeType.ALL)
	private Set<ComidaDieta> comidasDieta = new HashSet<ComidaDieta>();
	
	public Plan getPlan() {
		return plan;
	}
	
	public void setPlan(Plan plan) {
		this.plan = plan;
	}
	
	private void agegarComidaDieta(ComidaDieta comidaDieta) {
		this.comidasDieta.add(comidaDieta);
	}
	
	public Set<ComidaDieta> getComidasDieta() {
		return comidasDieta;
	}
	
	public Dieta(Plan plan, Date fecha) {
		
		this.setPlan(plan);
		this.setFecha(fecha);
		this.clonarComidas(plan);
		
	}
	
	private void clonarComidas(Plan plan) {
		
		for (ComidaPlan comidaPlan : plan.getComidasPlan()) {
			
			ComidaDieta comidaDieta = new ComidaDieta();
			
			comidaDieta.setTipo(comidaPlan.getTipo());
			this.asignarAlimentos(comidaPlan, comidaDieta);
			this.agegarComidaDieta(comidaDieta);
			
		}
		
	}
	
	public List<Ingerido> getAlimentosTipoComida(String tipoComida) {
		List<Ingerido> ingeridos = new ArrayList<Ingerido>();
		
		for (ComidaDieta comidaDieta : getComidasDieta()) {
			if (TipoComida.valueOf(tipoComida).equals(comidaDieta.getTipo())) {
				ingeridos.addAll(comidaDieta.getIngeridos());
			}
		}
		return ingeridos;
	}
	
	/**
	 * Este metodo es para cargar los alimentos "SUGERIDOS" con alimento (o comible) y cantidad de porciones de cada uno
	 * para que le figuren en la dieta.
	 * Asigna los alimentos sugeridos a la dieta.
	 * 
	 * ESTO NO ES PARA CARGAR LOS INGERIDOS POR EL USUARIO!
	 * 
	 * @param comidaPlan y @param comidaDieta son del mismo TipoComida
	 * */
	private void asignarAlimentos(ComidaPlan comidaPlan, ComidaDieta comidaDieta) {
		
		for (PorcionPlan porcionPlan : comidaPlan.getPorciones()) {
			
			Alimento alimento = buscarAlimento(porcionPlan.getGenero());
			
			if (alimento != null) {
				// acá hay que preguntar por que la dieta no se haya pasado de la cantidad de calorias del plan.
				// Podemos usar el metodo calcularCaloriasSugeridas.
				// Si ya usó todas las calorias que había, entonces cortamos con la asignación de alimentos...
				// TODO ver qué onda con esto
				// ver si podemos asignarle el porcentaje a cada comida como haciamos antes
				
				Ingerido ingerido = new Ingerido(alimento, porcionPlan.getCantidadDePorciones());
				
				comidaDieta.agregarIngerido(ingerido);
				
			}
			else {
				System.err.println("********* NO encuentro alimento para el genero: " + porcionPlan.getGenero());
			}
		}
	}

	public static Dieta findByDiaActual(Long planId) {
		return find("fecha = ? AND plan.id = ?", new Date(), planId).first();
	}
	
	public static Dieta findByFecha(Long planId, Date date) {
		return find("fecha = ? AND plan.id = ?", date, planId).first();
	}

	public Date getFecha() {
		return fecha;
	}

	public void setFecha(Date fecha) {
		this.fecha = fecha;
	}
	
	public Integer calcularCaloriasConsumidas() {
		
		Integer totalCalorias = 0;
		
		for (ComidaDieta comida : getComidasDieta()) {
			totalCalorias += comida.calcularCaloriasIngeridas();
		}
		
		return totalCalorias;
	}
	
	public Integer calcularCaloriasSugeridas() {
		
		Integer totalCalorias = 0;
		
		for (ComidaDieta comida : getComidasDieta()) {
			totalCalorias += comida.calcularCaloriasSugeridas();
		}
		
		return totalCalorias;
	}
	
	/**
	 * Este metodo generar las dietas con comidas equilibradas segun
	 * el plan y las porciones de alimentos en cada comida
	 * */
	private Alimento buscarAlimento(Genero genero) {
		
		List<Alimento> alimentosPosibles = new ArrayList<Alimento>();
		
		for (TipoAlimento tipoAlimento : TipoAlimento.values()) {
			
			if (genero.equals(tipoAlimento.getGenero())) {
				
				List<Alimento> alimentos = Alimento.find("byTipoElike", tipoAlimento).fetch();
				
				alimentosPosibles.addAll(alimentos);
			}
			
		}
		
		System.out.println("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"+alimentosPosibles);
		// Tirar un random entre estos alimentos que encontró y asignarlos a cada comida
		return (alimentosPosibles.isEmpty())? null : alimentosPosibles.get((int)(Math.random() * alimentosPosibles.size()));
		
	}
	
}
